﻿using AutoMapper;
using ManagementApi.Models;
using ManagementApi.Models.Cms.Request;
using ManagementApi.Models.Project;
using ManagementApi.Services.Cms.Request;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.AspNetCore.Mvc;
using Minio.DataModel;
using Modules;
using Modules.Cms;
using Modules.Corp;
using Modules.FaceScan;
using Modules.FaceScan.Entitys;
using Modules.Person;
using Modules.Project;
using Modules.Project.Entitys;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using PmSoft.ApplicationContext;
using PmSoft.Entity;
using PmSoft.Exceptions;
using System.ComponentModel.DataAnnotations;
using static Modules.Project.ProjectConstants;
using static Modules.Project.ProjectLockLogConstants;

namespace ManagementApi.Controllers;

/// <summary>
/// 一体化平台支撑Api接口
/// </summary>
[Route("/api/v1/cmssupportApi")]
[ApiController]
public class CmsSupportApiController : ControllerBase
{
    private readonly CmsSupportService cmsSupportService;
    private readonly PersonService personService;
    private readonly FacePhotoService personFaceService;
    private readonly ProjectService projectService;
    private readonly ProjectCorpService projectCorpService;
    private readonly ProjectGroupService projectGroupService;
    private readonly ProjectGroupMemberService projectGroupMemberService;
    private readonly CorpService corpService;
    private readonly IMapper mapper;
    private readonly IApplicationContext applicationContext;
    private readonly ILogger logger;
    private readonly ProjectLockLogService projectLockLogService;

    public CmsSupportApiController(CmsSupportService cmsSupportService, PersonService personService, FacePhotoService personFaceService, ProjectService projectService, ProjectCorpService projectCorpService, ProjectGroupService projectGroupService, ProjectGroupMemberService projectGroupMemberService, CorpService corpService, IMapper mapper, IApplicationContext applicationContext, ILogger<CmsSupportApiController> logger, ProjectLockLogService projectLockLogService)
    {
        this.cmsSupportService = cmsSupportService;
        this.personService = personService;
        this.personFaceService = personFaceService;
        this.projectService = projectService;
        this.projectCorpService = projectCorpService;
        this.projectGroupService = projectGroupService;
        this.projectGroupMemberService = projectGroupMemberService;
        this.corpService = corpService;
        this.mapper = mapper;
        this.applicationContext = applicationContext;
        this.logger = logger;
        this.projectLockLogService = projectLockLogService;
    }

    #region 实名制向一体化提供接口

    /// <summary>
    /// 根据项目编号查询项目信息
    /// </summary>
    /// <param name="req"></param>
    /// <returns></returns>
    [HttpGet("getProject")]
    public ApiResult GetProject(EncryptMess<PrjReq> req)
    {
        PrjReq? prjReq = req.GetParame();
        if (prjReq == null)
            return ApiResult.Failure("参数无法解析");
        logger.LogInformation($"getProject ，根据项目编号查询项目信息，prjNum：{prjReq.PrjNum}");
        ProjectInfo? projectInfo = projectService.GetProjectInfoByPrjNum(prjReq.PrjNum);
        if (projectInfo == null)
            return ApiResult.Failure("未查询到项目信息");
        return ApiResult.Success("成功", mapper.Map(projectInfo, new ProjectInfoDto()));
    }

    /// <summary>
    /// 人员信息同步(一体化平台项目人员发生变更)
    /// </summary>
    /// <param name="req"></param>
    /// <returns></returns>
    /// <exception cref="BusinessException"></exception>
    [HttpPost("syncPerson")]
    public ApiResult SyncPerson(EncryptMess<PrjPersonInfoReq> req)
    {
        PrjPersonInfoReq? prjPersonInfo = req.GetParame();
        if (prjPersonInfo == null)
            return ApiResult.Failure("参数无法解析").Encrypt();
        logger.LogInformation($"syncPerson ，人员信息同步，参数：{JsonConvert.SerializeObject(prjPersonInfo)}");

        ProjectInfo? projectInfo = projectService.GetProjectInfoByPrjNum(prjPersonInfo.PrjNum);
        if (projectInfo == null)
            return ApiResult.Failure("未查询到项目信息");

        CorpInfo? corpInfo = corpService.GetCorpInfo(prjPersonInfo.QYXYCode);
        if (corpInfo == null)
            return ApiResult.Failure("未查询到企业信息");

        IEnumerable<PersonInfo> personInfos = personService.GetPersonsByCardNumbers(prjPersonInfo.persons.Select(a => a.GRIDCard));
        IEnumerable<FacePhoto> personFaces = personFaceService.GetPersonFacesByIdCards(prjPersonInfo.persons.Select(a => a.GRIDCard));
        //IEnumerable<ProjectCorp> projectCorps = projectCorpService.GetProjectCorpsByProjectId(projectInfo.ProjectId);
        //查询总包和监理管理班组
        //IEnumerable<ProjectGroup> projectGroups = projectGroupService.GetProjectGroupsByProjectId(projectInfo.ProjectId).Where(a => a.IsManagerGroup == true);
        //IEnumerable<CorpInfo>? corpInfos = corpService.GetCorpsByCorpIds(projectCorps.Select(a => a.CorpId));

        try
        {
            applicationContext.Transaction.Begin();
            foreach (var item in prjPersonInfo.persons)
            {
                cmsSupportService.SyncPersonNoTransaction(projectInfo, item, personInfos, personFaces, projectCorps, projectGroups);
            }
            applicationContext.Transaction.Complete();
            return ApiResult.Success($"人员信息同步成功").Encrypt();
        }
        catch (Exception ex)
        {
            applicationContext.Transaction.Abort();
            logger.LogError($"人员信息同步失败,原因：{ex.Message}");
            return ApiResult.Failure($"人员信息同步失败,原因：{ex.Message}");
        }
    }

    /// <summary>
    /// 一体化平台自动解锁
    /// </summary>
    /// <param name="req"></param>
    /// <returns></returns>
    [HttpPost("UnlockRec")]
    public ApiResult UnlockRec(EncryptMess<ProjectUnLockReq> req)
    {
        ProjectUnLockReq? projectUnLockReq = req.GetParame();
        if (projectUnLockReq == null)
            return ApiResult.Failure("参数无法解析").Encrypt();
        logger.LogInformation($"UnlockRec ，一体化平台自动解锁，参数：{JsonConvert.SerializeObject(projectUnLockReq)}");
        ProjectLockLog? projectLockLog = projectLockLogService.GetProjectLockLogByCode(projectUnLockReq.LockId);
        if (projectLockLog == null)
            return ApiResult.Failure("未查询到解上锁信息");
        projectLockLog.PushTime = DateTime.Now;
        projectLockLog.PushResult = 1;
        projectLockLog.UnlockTime = DateTime.Now;
        projectLockLog.HasPush = true;
        projectLockLog.PushResponseTime = DateTime.Now;
        projectLockLog.DataSourse = 解锁数据来源.自动;
        projectLockLogService.Update(projectLockLog);
        return ApiResult.Success($"编号{projectUnLockReq.LockId}自动解锁成功");
    }

    #endregion 实名制向一体化提供接口

    #region 实名制请求一体化接口

    /// <summary>
    /// 同步项目信息
    /// </summary>
    /// <param name="projectId">项目id</param>
    /// <returns></returns>
    [HttpPut("syncProject/{projectId}")]
    [Authorize(Roles = "Manager,Corp")]
    public ApiResult SyncProject([Required(ErrorMessage = "项目id不能为空")] int projectId)
    {
        ProjectInfo? projectInfo = projectService.GetProjectInfo(projectId);
        if (projectInfo == null)
            return ApiResult.Failure("未查询到项目信息");
        VerifyProject(projectInfo);
        cmsSupportService.SyncProject(projectInfo);
        return ApiResult.Success($"项目{projectInfo.PrjNum}信息同步成功");
    }

    /// <summary>
    /// 推送项目信息到一体化平台
    /// </summary>
    /// <param name="projectId"></param>
    /// <returns></returns>
    [HttpPost("publishProject/{projectId}")]
    [Authorize(Roles = "Manager,Corp")]
    public ApiResult PublishProject([Required(ErrorMessage = "项目id不能为空")] int projectId)
    {
        ProjectInfo? projectInfo = projectService.GetProjectInfo(projectId);
        if (projectInfo == null)
            return ApiResult.Failure("未查询到项目信息");
        VerifyProject(projectInfo);
        cmsSupportService.PublishProject(projectInfo);
        return ApiResult.Success($"项目{projectInfo.PrjNum}信息推送成功");
    }

    /// <summary>
    /// 手动推送解上锁记录
    /// </summary>
    /// <param name="code"></param>
    /// <returns></returns>
    [HttpPost("projectLock/{code}")]
    [Authorize(Roles = "Manager,Corp")]
    public ApiResult ProjectLock(string code)
    {
        ProjectLockLog? projectLockLog = projectLockLogService.GetProjectLockLogByCode(code);
        if (projectLockLog == null)
            return ApiResult.Failure("未查询到解上锁信息");
        ProjectInfo? projectInfo = projectService.GetProjectInfo(projectLockLog.ProjectId);
        if (projectInfo == null)
            return ApiResult.Failure("未查询到项目信息");
        if (projectLockLog.HasLocked)
        {
            //推送上锁记录

            CorpInfo? corpInfo = corpService.GetCorpInfo(projectInfo.LumpContractorCorpId);
            if (corpInfo == null)
                return ApiResult.Failure($"当前编号对应的项目总承包单位不存在，不能推送到一体化平台");

            ProjectLockReq req = new() { OrgID = code, CorpCode = corpInfo.Code, PrjName = projectInfo.Name };
            cmsSupportService.ProjectLock(req);
        }
        else
        {
            //推送解锁记录
            cmsSupportService.ProjectUnlock(code);
        }

        return ApiResult.Success($"编号{code}信息推送成功");
    }

    #endregion 实名制请求一体化接口

    #region 私有方法

    /// <summary>
    /// 验证
    /// </summary>
    /// <param name="projectInfo"></param>
    /// <exception cref="BusinessException"></exception>
    private void VerifyProject(ProjectInfo projectInfo)
    {
        if (projectInfo.AuditStatus != 项目审核状态.通过)
            throw new BusinessException($"项目{projectInfo.PrjPlanNum}没有审核通过，不能同步");
        if (projectInfo.PrjStatus != 项目状态.在建)
            throw new BusinessException($"项目{projectInfo.PrjPlanNum}当前项目状态不是在建，不能同步");
        if (string.IsNullOrEmpty(projectInfo.BuilderLicences))
            throw new BusinessException($"项目{projectInfo.PrjPlanNum}施工许可证编号不存在，不能同步");
        if (projectInfo.IsSync)
            throw new BusinessException($"项目{projectInfo.PrjPlanNum}已同步，不能同步");
    }

    #endregion 私有方法
}